package cn.demoncat.util.mybatis.plus.base;

import cn.demoncat.util.lang.CollectionUtil;
import cn.demoncat.util.lang.ParamEmptyUtil;
import cn.demoncat.util.lang.ReflectClassUtil;
import cn.demoncat.util.lang.entity.MysqlQuery;
import cn.demoncat.util.mybatis.plus.method.InsertIgnore;
import cn.demoncat.util.mybatis.plus.method.ReplaceInto;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import org.apache.commons.collections4.CollectionUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * BaseServiceImpl
 *
 * @see <a href="https://mybatis.plus/guide/crud-interface.htm">数据库操作</a>
 *
 * @see <a href="https://mp.baomidou.com/guide/wrapper.html">条件表达式</a>
 *
 * @author 延晓磊
 * @since 2021年08月23日
 */
public class BaseServiceImpl<M extends BaseMapper<T>, T> extends ServiceImpl<M,T> implements BaseService<T> {

    /**
     * 创建PO实例
     *
     * @return
     *
     * @author 延晓磊
     * @since 2022年05月23日
     */
    @Override
    public T instanceEntity(){
        return ReflectClassUtil.instance(this.getEntityClass());
    }

    /**
     * ID删除
     *
     * @param id
     * @return
     *
     * @author 延晓磊
     * @since 2021年08月23日
     */
    @Override
    public boolean removeById(Serializable id) {
        ParamEmptyUtil.checkNull(id);
        return super.removeById(id);
    }

    /**
     * ID查询
     *
     * @param id
     * @return
     *
     * @author 延晓磊
     * @since 2021年08月23日
     */
    @Override
    public T getById(Serializable id) {
        ParamEmptyUtil.checkNull(id);
        return super.getById(id);
    }

    /**
     * ID列表查询
     *
     * @param idList
     * @return
     *
     * @author 延晓磊
     * @since 2021年08月23日
     */
    @Override
    public List<T> listByIds(Collection<? extends Serializable> idList) {
        if (CollectionUtils.isEmpty(idList)) {
            return new ArrayList<>();
        }
        return this.getBaseMapper().selectBatchIds(idList);
    }

    /**
     * 自定义搜索（需要XML支持）
     *
     * @param query 查询参数：字段、条件、分组、排序等，支持子查询
     * @return
     *
     * @author 延晓磊
     * @since 2021年11月25日
     */
    @Override
    public List<T> list(MysqlQuery query) {
        return this.getBaseMapper().select(query);
    }

    /**
     * 批量添加（解决saveBatch循环插入速度慢的问题，需要XML支持）
     *
     * 1、如果赋值ID，使用自定义ID；如果ID为null，使用数据库自增
     * 2、添加后可以通过o.getId()获取主键
     * 3、如果使用INSERT INTO，插入重复时抛异常；如果使用INSERT IGNORE INTO 插入重复时更新
     *
     * @param os
     * @return 是否插入，列表为空是返回false
     *
     * @author 延晓磊
     * @since 2021年11月25日
     */
    @Override
    public boolean batchSave(List<T> os) {
        return batchSave(os, 1000);
    }

    /**
     * 批量添加（解决saveBatch循环插入速度慢的问题，需要XML支持）
     *
     * 1、如果赋值ID，使用自定义ID；如果ID为null，使用数据库自增
     * 2、添加后可以通过o.getId()获取主键
     * 3、如果使用INSERT INTO，插入重复时抛异常；如果使用INSERT IGNORE INTO 插入重复时更新
     *
     * @param os
     * @param size  批次数量
     * @return 是否插入，列表为空是返回false
     *
     * @author 延晓磊
     * @since 2021年11月25日
     */
    @Override
    public boolean batchSave(List<T> os, int size) {
        if (os == null || os.isEmpty()) {
            return false;
        }
        CollectionUtil.batchs2(os, size, list -> this.getBaseMapper().batchSave(list));
        return true;
    }

    /**
     * 添加 InsertIgnore
     *
     * @param o 如果存在（主键、唯一索引）则忽略，否则添加
     * @return
     *
     * @author 延晓磊
     * @since 2022年02月08日
     */
    @Override
    public boolean ignoreSave(T o) {
        return SqlHelper.retBool(this.getBaseMapper().insertIgnore(o));
    }

    /**
     * 批量添加 InsertIgnore
     *
     * @param os 如果存在（主键、唯一索引）则忽略，否则添加
     * @return
     *
     * @author 延晓磊
     * @since 2022年02月08日
     */
    @Override
    public boolean ignoreSaveBatch(Collection<T> os) {
        String sqlStatement = getSqlStatement(InsertIgnore.NAME);
        return executeBatch(os, 1000, (sqlSession, entity) -> sqlSession.insert(sqlStatement, entity));
    }

    /**
     * 添加 ReplaceInto
     *
     * @param o 如果存在（主键、唯一索引）则更新（跨多条数据时合并为1条），否则添加
     * @return
     *
     * @author 延晓磊
     * @since 2022年02月08日
     */
    @Override
    public boolean replaceSave(T o) {
        return SqlHelper.retBool(this.getBaseMapper().replaceInto(o));
    }

    /**
     * 批量添加 ReplaceInto
     *
     * @param os 如果存在（主键、唯一索引）则更新（跨多条数据时合并为1条），否则添加
     * @return
     *
     * @author 延晓磊
     * @since 2022年02月08日
     */
    @Override
    public boolean replaceSaveBatch(Collection<T> os) {
        String sqlStatement = getSqlStatement(ReplaceInto.NAME);
        return executeBatch(os, 1000, (sqlSession, entity) -> sqlSession.insert(sqlStatement, entity));
    }

    /**
     * 批量添加
     *
     * @param os
     * @return
     *
     * @author 延晓磊
     * @since 2022年04月14日
     */
    @Override
    public boolean saveBatch(Collection<T> os) {
        if (CollectionUtils.isEmpty(os)) {
            return false;
        }
        return super.saveBatch(os);
    }

    /**
     * 批量修改
     *
     * @param os
     * @return
     *
     * @author 延晓磊
     * @since 2022年04月14日
     */
    @Override
    public boolean updateBatchById(Collection<T> os) {
        if (CollectionUtils.isEmpty(os)) {
            return false;
        }
        return super.updateBatchById(os);
    }

    /**
     * 清空
     *
     * @return
     */
    @Override
    public void truncate() {
        this.getBaseMapper().truncate();
    }

    /**
     * 获取SqlStatement
     *
     * @param method
     * @return
     *
     * @author 延晓磊
     * @since 2022年02月08日
     */
    protected String getSqlStatement(String method) {
        return mapperClass.getName() + StringPool.DOT + method;
    }
}


